package org.totoro.patterns.behavior.interpreter.demo;

import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;

/**
 * @author linxiaohui
 */
public enum Operator {

    /**
     * equals
     **/
    EQ {
        @Override
        public boolean evaluate(Object a, Object b) {
            return Objects.equals(a, b);
        }
    },
    /**
     * not equals
     **/
    NEQ {
        @Override
        public boolean evaluate(Object a, Object b) {
            return !EQ.evaluate(a, b);
        }
    },
    /**
     * less
     **/
    LT {
        @Override
        public boolean evaluate(Object a, Object b) {

            return CompareUtils.compare(a, b) < 0;
        }
    },
    /**
     * less or equal
     **/
    LE {
        @Override
        public boolean evaluate(Object a, Object b) {

            return CompareUtils.compare(a, b) <= 0;
        }
    },
    /**
     * greater
     **/
    GT {
        @Override
        public boolean evaluate(Object a, Object b) {
            return CompareUtils.compare(a, b) > 0;
        }
    },
    /**
     * greater or equal
     **/
    GE {
        @Override
        public boolean evaluate(Object a, Object b) {
            return CompareUtils.compare(a, b) >= 0;
        }
    },
    /**
     * contain in
     **/
    CI {
        @Override
        public boolean evaluate(Object a, Object b) {
            return String.valueOf(a).contains(String.valueOf(b));
        }
    },
    /**
     * not contain in
     **/
    NCI {
        @Override
        public boolean evaluate(Object a, Object b) {
            return !CI.evaluate(a, b);
        }
    },
    /**
     * begin with
     **/
    BW {
        @Override
        public boolean evaluate(Object a, Object b) {
            return String.valueOf(a).startsWith(String.valueOf(b));
        }
    },
    /**
     * not begin with
     **/
    NBW {
        @Override
        public boolean evaluate(Object a, Object b) {
            return !BW.evaluate(a, b);
        }
    },
    /**
     * end with
     **/
    EW {
        @Override
        public boolean evaluate(Object a, Object b) {
            return String.valueOf(a).endsWith(String.valueOf(b));
        }
    },
    /**
     * not end with
     **/
    NEW {
        @Override
        public boolean evaluate(Object a, Object b) {
            return !EW.evaluate(a, b);
        }
    },
    /**
     * in
     **/
    IN {
        @Override
        public boolean evaluate(Object a, Object b) {
            if (null == a || null == b) {
                return false;
            }
            if (b instanceof String) {
                return Arrays.asList(((String) b).split(",")).contains(String.valueOf(a));
            }
            if (b instanceof Collection) {
                return ((Collection) b).contains(a);
            }
            if (b.getClass().isArray()) {
                Object[] array = (Object[]) b;
                return Arrays.asList(array).contains(a);
            }
            return false;
        }
    },
    /**
     * not in
     **/
    NIN {
        @Override
        public boolean evaluate(Object a, Object b) {
            return !IN.evaluate(a, b);
        }
    },
    /**
     * is null
     **/
    NU {
        @Override
        public boolean evaluate(Object a, Object b) {
            return null == a;
        }
    },
    /**
     * is not null
     **/
    NNU {
        @Override
        public boolean evaluate(Object a, Object b) {
            return null != a;
        }
    },
    EMP {
        @Override
        public boolean evaluate(Object a, Object b) {
            if (null == a) {
                return true;
            } else if (a instanceof String) {
                return (String) a == null || a.equals("");
            } else if (a instanceof Collection) {
                return ((Collection) a).isEmpty();
            } else if (a.getClass().isArray()) {
                return ((Object[]) a).length == 0;
            }
            return false;
        }
    },
    NEMP {
        @Override
        public boolean evaluate(Object a, Object b) {
            return !EMP.evaluate(a, b);
        }
    };

    public abstract boolean evaluate(Object a, Object b);
}